/**
 * My simple header template from child directory
 * HandToWallCoordinator.java - ${projectName} - ${organizationName} - ${inceptionYear}
 */
package FourthTry;

/*
 * #%L
 * Ability-tester
 * %%
 * Copyright (C) 2014 AmazingSERKU
 * %%
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * #L%
 */


/**
 * Created with IntelliJ IDEA.
 * User: Gauss
 * Date: 29.01.14
 * Time: 0:05
 * To change this template use File | Settings | File Templates.
 */
public class HandToWallCoordinator implements ICoordinator {

    private IMovable movable;
    private Direction direction;
    private IArea area;
    private Coordinates destinationCoordinates;

    public HandToWallCoordinator(IMovable movable, Coordinates destinationCoordinates) {
        this.movable = movable;
        this.destinationCoordinates = destinationCoordinates;
        this.direction = Direction.calculateDirection(movable.getCoordinates(), destinationCoordinates);
    }

    @Override
    public ICoordinator copyState(ICoordinator coordinator) {
        this.setArea(coordinator.getArea());
        return this;
    }

    @Override
    public CoordinatorCell getNextCell(Coordinates coordinates) {
        if (!coordinates.equals(destinationCoordinates)) {
            return nextCell(coordinates);
        } else {
            return endOfAlgorithmCell(coordinates);
        }
    }

    protected CoordinatorCell nextCell(Coordinates coordinates) {
        if (isCellFree(coordinates, direction.counterClockWise())) {
            return getCellOnDirection(coordinates, direction.counterClockWise());
        } else {
            return turnRightOrMoveForward(coordinates);
        }
    }

    protected CoordinatorCell turnRightOrMoveForward(Coordinates coordinates) {
        int counter = 0;
        while(!isCellFree(coordinates, direction) && (counter < 4)) {
            direction = direction.clockWise();
            counter++;
        }
        if (counter==4) throw new RuntimeException("Dead end");
        return getCellOnDirection(coordinates, direction);
    }

    protected boolean isCellFree(Coordinates coordinates, Direction direction) {
        Coordinates temp = new Coordinates(coordinates);
        direction.changeCoordinate(temp);
        Cell cell = area.getCell(temp);
        return !cell.isAbroad()&& movable.analyzeCell(cell);
    }

    private CoordinatorCell getCellOnDirection(Coordinates coordinates, Direction direction) {
        Coordinates temp = new Coordinates(coordinates);
        direction.changeCoordinate(temp);
        this.direction = direction;
        return new CoordinatorCell(area.getCell(temp), false);
    }

    private CoordinatorCell endOfAlgorithmCell(Coordinates coordinates) {
        return new CoordinatorCell(coordinates, true);
    }

    @Override
    public IArea getArea() {
        return area;
    }

    @Override
    public void setArea(IArea area) {
        this.area = area;
    }
}
